package com.xiannimei.service.oauth;

import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.xiannimei.BusinessException;
import com.xiannimei.model.Platform;

@Service("oauthSina")
@Transactional
public class OAuthManagerImplSina extends OAuthManagerAbstractImpl {

	@Value("#{oauth_sina['appKey']}")
	private String client_id;
	@Value("#{oauth_sina['appSecret']}")
	private String client_secret;
	@Value("#{oauth_sina['grant_type']}")
	private String grant_type;
	@Value("#{oauth_sina['redirect_uri']}")
	private String redirect_uri;
	@Value("#{oauth_sina['urlAuthorize']}")
	private String urlAuthorize;
	@Value("#{oauth_sina['urlGetToken']}")
	private String urlGetToken;
	@Value("#{oauth_sina['scope']}")
	private String scope;

	@Value("#{oauth_sina['display']}")
	private String display;
	@Value("#{oauth_sina['forcelogin']}")
	private String forcelogin;
	@Value("#{oauth_sina['language']}")
	private String language;
	@Value("#{oauth_sina['urlGetUserInfo']}")
	private String urlGetUserInfo;
	@Value("#{oauth_sina['urlGetProvince']}")
	private String urlGetProvince;
	@Value("#{oauth_sina['urlGetCity']}")
	private String urlGetCity;

	private Map<String, String> locMap = new HashMap<String, String>();
	private DecimalFormat df = new DecimalFormat("000");
	private String defaultCountyCode = "001";

	@Override
	public String getLoginUrl(String state) {
		return genericUrl(urlAuthorize, "client_id", client_id, "redirect_uri", redirect_uri, "scope", scope, "forcelogin",
				forcelogin, "language", language, "display", display, "state", state);
	}

	@Override
	public String getNick(JSONObject userJo) {
		if (userJo.has("screen_name")) {
			return userJo.getString("screen_name");
		} else {
			log.warn("get sina user error :\n" + userJo);
			throw new BusinessException(E_USERJOERR);
		}
	}

	@Override
	public Integer getPlatformId() {
		return Platform.TYPE_SINA;
	}

	@Override
	OAuthProfile localize(String code) {
		JSONObject tokenJo = postForJson(urlGetToken, "client_id", client_id, "client_secret", client_secret, "grant_type",
				grant_type, "redirect_uri", redirect_uri, "code", code);
		if (tokenJo.has("access_token") && tokenJo.has("uid") && tokenJo.has("expires_in")) {
			String token = tokenJo.getString("access_token");
			String uid = tokenJo.getString("uid");
			Integer remain = tokenJo.getInt("expires_in");
			return login(token, uid, remain);
		} else {
			log.warn("get sina token error :\n" + tokenJo);
			throw new BusinessException(E_TOKENJOERR);
		}
	}

	@Override
	JSONObject getThirdPartyUser(String token, String uid) {
		return JSONObject.fromObject(doGet(genericUrl(urlGetUserInfo, "access_token", token, "uid", uid)));
	}

	/**
	 * 获取用户所在省
	 * 
	 * @param userJo 用户信息
	 * @param accessToken 授权
	 * @return 用户所在省
	 */
	String localizeProvince(JSONObject userJo, String accessToken) {
		String key = defaultCountyCode + df.format(Integer.valueOf(userJo.getString("province")));
		if (locMap.containsKey(key) == false)
			writeLocMap(doGet(genericUrl(urlGetProvince, "access_token", accessToken, "country", defaultCountyCode)));
		return locMap.get(key);
	}

	/**
	 * 获取用户所在市
	 * 
	 * @param userJo 用户信息
	 * @param accessToken 授权
	 * @return 用户所在市
	 */
	String localizeCity(JSONObject userJo, String accessToken) {
		String key = defaultCountyCode + df.format(Integer.valueOf(userJo.getString("province")))
				+ df.format(Integer.valueOf(userJo.getString("city")));
		if (locMap.containsKey(key) == false)
			writeLocMap(doGet(genericUrl(urlGetCity, "access_token", accessToken, "province", key.substring(0, 6))));
		return locMap.get(key);
	}

	/**
	 * 将新浪城市ID对照表写入本实体
	 * 
	 * @param jo 新浪返回的部分城市对照表
	 */
	private void writeLocMap(String jo) {
		JSONArray ja = JSONArray.fromObject(jo);
		for (int i = 0; i < ja.size(); i++) {
			JSONObject jsonObject = ja.getJSONObject(i);
			Iterator<?> it = jsonObject.keys();
			if (it.hasNext()) {
				String key = (String) it.next();
				locMap.put(key, (String) jsonObject.get(key));
			}
		}
	}

	String localizeGender(String gender) {
		String p = null;
		if ("m".equals(gender))
			p = "男";
		else if ("f".equals(gender))
			p = "女";
		return p;
	}
}
